#include "sht30.h" 
#include "delay.h" 
#include <math.h>    //Keil library  
#include <stdio.h>   //Keil library
 
//********************************************************************

//产生IIC起始信号
static void IIC_Start(void)
{
	SDA_OUT();     //sda线输出
	IIC_SDA=1;	  	  
	IIC_SCL=1;
	delay_us(4);
 	IIC_SDA=0;//START:when CLK is high,DATA change form high to low 
	delay_us(4);
	IIC_SCL=0;//钳住I2C总线，准备发送或接收数据 
}	  
//产生IIC停止信号
static void IIC_Stop(void)
{
	SDA_OUT();//sda线输出
	IIC_SCL=0;
	IIC_SDA=0;//STOP:when CLK is high DATA change form low to high
 	delay_us(4);
	IIC_SCL=1; 
	IIC_SDA=1;//发送I2C总线结束信号
	delay_us(4);							   	
}
//等待应答信号到来
//返回值：1，接收应答失败
//        0，接收应答成功
static u8 IIC_Wait_Ack(void)
{
	u16 ucErrTime=0;
	SDA_IN();      //SDA设置为输入  
	IIC_SDA=1;delay_us(1);	   
	IIC_SCL=1;delay_us(1);	 
	while(READ_SDA)
	{
		ucErrTime++;
		if(ucErrTime>60000)
		{
			IIC_Stop();
			return 1;
		}
	}
	IIC_SCL=0;//时钟输出0 	   
	return 0;  
} 
//产生ACK应答
static void IIC_Ack(void)
{
	IIC_SCL=0;
	SDA_OUT();
	IIC_SDA=0;
	delay_us(2);
	IIC_SCL=1;
	delay_us(2);
	IIC_SCL=0;
}
//不产生ACK应答		    
static void IIC_NAck(void)
{
	IIC_SCL=0;
	SDA_OUT();
	IIC_SDA=1;
	delay_us(2);
	IIC_SCL=1;
	delay_us(2);
	IIC_SCL=0;
}					 				     
//IIC发送一个字节
//返回从机有无应答
//1，有应答
//0，无应答			  
static void IIC_Send_Byte(u8 txd)
{                        
    u8 t;   
	SDA_OUT(); 	    
    IIC_SCL=0;//拉低时钟开始数据传输
    for(t=0;t<8;t++)
    {              
        IIC_SDA=(txd&0x80)>>7;
        txd<<=1; 	  
		delay_us(2);   //对TEA5767这三个延时都是必须的
		IIC_SCL=1;
		delay_us(2); 
		IIC_SCL=0;	
		delay_us(2);
    }	 
} 	    
//读1个字节，ack=1时，发送ACK，ack=0，发送nACK   
static u8 IIC_Read_Byte(u8 ack)
{
	u8 i,receive=0;
	SDA_IN();//SDA设置为输入
    for(i=0;i<8;i++ )
	{
        IIC_SCL=0; 
        delay_us(2);
		IIC_SCL=1;
        receive<<=1;
        if(READ_SDA)receive++;   
		delay_us(1); 
    }					 
    if (!ack)
        IIC_NAck();//发送nACK
    else
        IIC_Ack(); //发送ACK   
    return receive;
}
//**********************************************************************
void SHT3x_Init(void)
{



        GPIO_InitTypeDef SHT30 = {0};
 
	  /* GPIO Ports Clock Enable */
	  __HAL_RCC_GPIOB_CLK_ENABLE();
 
	  //__HAL_RCC_GPIOC_CLK_ENABLE();

	  /*Configure GPIO pin Output Level */
	
	  /*Configure GPIO pin : PC12 */
	  SHT30.Pin = GPIO_PIN_5|GPIO_PIN_6;
	  SHT30.Mode = GPIO_MODE_OUTPUT_PP;
	  SHT30.Pull = GPIO_NOPULL;
	  SHT30.Speed = GPIO_SPEED_FREQ_HIGH;
	  HAL_GPIO_Init(GPIOB, &SHT30);
	  /*Configure GPIO pin : PC12 */
      HAL_GPIO_WritePin(GPIOB,  GPIO_PIN_5|GPIO_PIN_6, GPIO_PIN_RESET);
	 

}

static etError SHT3x_StartWriteAccess(void)
{
 u8 err;
 IIC_Start();
 IIC_Send_Byte(DevAddr<<1);
 err=IIC_Wait_Ack();
 return err;
}
static etError SHT3x_StartReadAccess(void)
{
 u8 err;
 IIC_Start();
 IIC_Send_Byte((DevAddr<<1)|0x01);
 err=IIC_Wait_Ack();
 return err;
}
static etError SHT3x_StopAccess(void)
{
 IIC_Stop();
 return NO_ERROR;
}
//返回正确:0, 错误:非0
static etError SHT3x_WriteCmd(u16 cmd)
{
 u8 err;
 IIC_Send_Byte(cmd>>8);  //写高字节
 err=IIC_Wait_Ack();
 if(err) return ACK_ERROR;
 IIC_Send_Byte(cmd&0xff); //写低字节
 err=IIC_Wait_Ack();
 if(err) return ACK_ERROR;
 else return NO_ERROR;
}



static u8 SHT3X_CalcCrc(u8 data[], u8 nbrOfBytes) 
{ 
  u8 bit;        // bit mask 
  u8 crc = 0xFF; // calculated checksum 
  u8 byteCtr;    // byte counter 
   
  // calculates 8-Bit checksum with given polynomial 
  for(byteCtr = 0; byteCtr < nbrOfBytes; byteCtr++) 
  { 
    crc ^= (data[byteCtr]); 
    for(bit = 8; bit > 0; --bit) 
    { 
      if(crc & 0x80) crc = (crc << 1) ^ POLYNOMIAL; 
      else           crc = (crc << 1); 
    } 
  } 
   
  return crc; 
} 
static etError SHT3X_CheckCrc(u8 data[], u8 nbrOfBytes, u8 checksum) 
{ 
    u8 crc;     // calculated checksum 
   // calculates 8-Bit checksum 
	crc = SHT3X_CalcCrc(data, nbrOfBytes); 
	 
	// verify checksum 
	if(crc != checksum) 
		return CHECKSUM_ERROR; 
	else				
		return NO_ERROR; 
 } 

float SHT3X_CalcTemperature(u16 rawValue) 
{ 
  // calculate temperature [°C] 
  // T = -45 + 175 * rawValue / (2^16-1) 
  return 175.0f * (float)rawValue / 65535.0f - 45.0f; 
} 
 
//----------------------------------------------------------------------------- 
float SHT3X_CalcHumidity(u16 rawValue) 
{ 
  // calculate relative humidity [%RH] 
  // RH = rawValue / (2^16-1) * 100 
  return 100.0f * (float)rawValue / 65535.0f; 
}

etError SHT3x_Read2ByteAndCrc(u16 *Res,u8 ack)
{
  u8 Byte[2];
  u8 checksum;
     Byte[0]=IIC_Read_Byte(ACK);
	 
	 Byte[1]=IIC_Read_Byte(ACK);
	 
	 checksum=IIC_Read_Byte(ack);              //读取crc
	 checksum=SHT3X_CheckCrc(Byte, 2,checksum);
	 *Res=(Byte[0]<<8)+Byte[1];
	 return checksum;
}

u8 SHT3x_ReadTempAndHumi(float *Temp,float* Humi)
{
 u8 err;
 u16 rawTemp,rawHumi;
 err = SHT3x_StartWriteAccess();
 err<<=2;
 err+=SHT3x_WriteCmd(CMD_MEAS_CLOCKSTR_H);
 SHT3x_StopAccess();
 delay_ms(50);
 err=SHT3x_StartReadAccess();
 if(err)
 	SHT3x_StartReadAccess();
 
 SHT3x_Read2ByteAndCrc(&rawTemp,ACK);
 SHT3x_Read2ByteAndCrc(&rawHumi,NACK);

 SHT3x_StopAccess();
 *Temp=SHT3X_CalcTemperature(rawTemp);
 *Humi=SHT3X_CalcHumidity(rawHumi);
 return err;
}


